﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using AccesoBD;
using System.Collections;
using System.Data.SqlClient;
using System.Data;
using CapaLogica.CL.Carrera;
using CapaLogica.CL.Bitacora;
using CapaLogica.CL.UtilidadesGenerales;
using CapaLogica.CL.Foro;
using CapaLogica.CL.Blog;


namespace CapaLogica.CL.Grupo
{
    public class GrupoPersistente
    {
        private AcessoBD _acceso = new AcessoBD();


        internal GrupoPersistente()
        {
                
        }

        /// <summary>
        /// Método de la clase encargada de insertar un nuevo Grupo y su asociacion con los profesores del grupo , a la BD
        /// </summary>
        /// <param name="pGrupo">Objeto grupo, tipo Grupo</param>
        /// <param name="pProfesores">Arreglo con los ids de los profesores, tipo ArrayList</param>
        /// <param name="pIdPeriodo">id del periodo lectivo, tipo int</param>
        /// <param name="pUsuario">Usuario que realiza la accion, tipo int</param>
        /// <remarks></remarks>
        public void insertarGrupo(CL_Grupo pGrupo, List<int> pProfesores, int pIdPeriodo, int pIdUsuario)//parametros del grupo
        {
            SqlConnection conexion = _acceso.GetConnection();
            conexion.Open();
            SqlTransaction transaction = conexion.BeginTransaction(IsolationLevel.ReadCommitted);

            try
            {
                Parametros[] parametros = new Parametros[3];
                string sql = @"insert into dbo.T_Grupo(num_grupo, id_periodo_lectivo, id_curso)
                                values(param1, param2, param3) ";

                parametros[0] = new Parametros(pGrupo.NumGrupo, "param1");
                parametros[1] = new Parametros(pIdPeriodo, "param2");
                parametros[2] = new Parametros(pGrupo.IdCurso, "param3");

                //registro de grupo
                pGrupo.Id = _acceso.executeSQLInsertTransation(transaction, sql, parametros);

                //registro bitacora
                Modulo.insertarBitacoraParaTransaccion(transaction, pIdUsuario,
                    "Creación de un nuevo Grupo", pGrupo.Id, 5, 1);

                //Registro de la asociacion de un profesor con un grupo
                int idRelacion = 0;
                Parametros[] paramGP = new Parametros[2];
                ForoPersistente persistenteForo = new ForoPersistente();
                 Cl_Foro foro = new Cl_Foro();
                
                for (int i = 0; i < pProfesores.Count; i++)
                {
                    sql = @"insert into dbo.T_Profesor_Grupo (id_usuario, id_grupo)
                            values (param1, param2) ";

                    paramGP[0] = new Parametros(pProfesores[i], "param1");
                    paramGP[1] = new Parametros(pGrupo.Id, "param2");
                    idRelacion = _acceso.executeSQLInsertTransation(transaction, sql, paramGP);

                    Modulo.insertarBitacoraParaTransaccion( transaction, pIdUsuario,
                        "Creación de la relación entre un grupo y un profesor.", idRelacion, 17, 1); 

                }


                transaction.Commit();
                conexion.Close();
            }
            catch (Exception ex)
            {
                try
                {
                    transaction.Rollback();
                    throw new Exception("Hubo un error al intentar crear el grupo. El grupo no ha sido creado.");
                }
                catch (Exception)
                {
                    throw new Exception("Error al crear el grupo.");
                }
            }
            finally
            {
                conexion.Close();
            }
        }


        /// <summary>
        /// Método de la clase encargada de insertar un nuevo Grupo y su asociacion con los profesores del grupo , a la BD
        /// </summary>
        /// <param name="pGrupo">Objeto grupo, tipo Grupo</param>
        /// <param name="pProfesores">Arreglo con los ids de los profesores, tipo ArrayList</param>
        /// <param name="pIdPeriodo">id del periodo lectivo, tipo int</param>
        /// <param name="pUsuario">Usuario que realiza la accion, tipo int</param>
        /// <remarks></remarks>
        public List<EsGrupo> buscarGrupo(int pidCarrera, int pidCurso)//parametros del grupo
        {
            List<EsGrupo> grupos = new List<EsGrupo>();
           
            EsGrupo grupo;

            string psp = @"dbo.sp_buscar_grupo";
            Parametros[] parametros = new Parametros[2];

                parametros[0] = new Parametros(pidCarrera, "id_carrera");
                parametros[1] = new Parametros(pidCurso, "id_curso");

            
            try
            {
                SqlDataReader reader = _acceso.execute_SP_Consulta(psp, parametros);

                while (reader.Read())
                {
                    grupo = new EsGrupo();
                    grupo.Id = reader.GetInt32(0) + "";
                    grupo.NombreCarrera = reader.GetValue(1).ToString();
                    grupo.NombreCurso = reader.GetValue(2).ToString();
                    grupo.NumGrupo = reader.GetValue(3).ToString();
                    grupos.Add(grupo);
                }
                reader.Close();

                return grupos;

            }
            catch (Exception ex)
            {
                throw new System.Exception(ex.Message);
            }

        }


        /// <summary>
        /// Método de la clase encargado de buscar un grupo por su id.
        /// </summary>
        /// <param name="pIdGrupo">Objeto grupo, tipo Grupo</param>
        /// <remarks></remarks>
        public CL_Grupo buscarGrupoPorId(int pIdGrupo)//parametros del grupo
        {

            string psp = @"dbo.sp_buscar_grupo_id";
            CL_Grupo grupo = null;
            Parametros[] parametros = new Parametros[1];
            parametros[0] = new Parametros(pIdGrupo, "id");
            try
            {
                SqlDataReader reader =_acceso.execute_SP_Consulta(psp, parametros);

                if (reader.Read())
                {
                    grupo = new CL_Grupo(reader.GetInt32(0), reader.GetInt32(2), Convert.ToInt32(reader.GetString(1)));
                }

                reader.Close();
                return grupo;

            }
            catch (Exception ex)
            {
                throw ex;
            }

        }

        /// <summary>
        /// Método de la clase encargado de buscar todos los grupos de un periodo lectivo.
        /// </summary>
        /// <param name="pIdPeriodo">Id del periodo lectivo, tipo int</param>
        /// <remarks></remarks>
        public List<CL_Grupo> buscarGruposDePeriodoLectivo(int pIdPeriodo)//parametros del grupo
        {

            string psp = @"dbo.sp_buscar_grupo_de_periodo_lectivo";
            CL_Grupo grupo = null;
            List<CL_Grupo> grupos = new List<CL_Grupo>();
            Parametros[] parametros = new Parametros[1];
            parametros[0] = new Parametros(pIdPeriodo, "idPeriodo");
            try
            {
                SqlDataReader reader = _acceso.execute_SP_Consulta(psp, parametros);

                while (reader.Read())
                {
                    grupo = new CL_Grupo(reader.GetInt32(0), reader.GetInt32(2), 
                                        Convert.ToInt32(reader.GetString(1)));
                    grupos.Add(grupo);
                }

                reader.Close();
                return grupos;

            }
            catch (Exception ex)
            {
                throw ex;
            }

        }

        /// <summary>
        /// Método de la clase encargada de cambiar los profesores de un grupo
        /// </summary>
        /// <param name="pIdGrupo">pIdGrupo, tipo int</param>
        /// <param name="pIdsAp">Ids de los profesores seleccionados, tipo List</int></param>
        /// <param name="pIdsBD">Ids de los profesores de la BD, tipo List</int></param>
        /// <param name="pUsuario">Usuario que realiza la accion, tipo int</param>
        /// <remarks></remarks>
        public void modificarGrupo(CL_Grupo pGrupo, List<int> pIdsAP, List<int> pIdsBD, int pIdUsuario, Boolean pModificar)
        {
            try
            {
                SqlTransaction transaction = null;
                if (pModificar == true)
                {
                    SqlConnection conexion = _acceso.GetConnection();
                    conexion.Open();
                    transaction = conexion.BeginTransaction(IsolationLevel.ReadCommitted);

                    String sqlUpdateGrupo = @"update dbo.T_Grupo 
                                                set num_grupo = param1
                                            where id_grupo= param2";

                    Parametros[] paramGrupo = new Parametros[2];
                    paramGrupo[0] = new Parametros(pGrupo.NumGrupo, "param1");
                    paramGrupo[1] = new Parametros(pGrupo.Id, "param2");

                    _acceso.executeSQLTransation(transaction, sqlUpdateGrupo, paramGrupo);
                    Modulo.insertarBitacoraParaTransaccion(transaction, pIdUsuario, "Cambio del número de un grupo.", pGrupo.Id, 5, 3);
                }
               

                EsBitacora bitacora = new EsBitacora();
                bitacora.Descripcion = "Cambio del profesor de un grupo";
                bitacora.IdUsuario = pIdUsuario;
                bitacora.Tipo= "17";


                string sqlUpdate = @"delete dbo.T_Profesor_Grupo 
                                    where id_grupo = param1 and
                                    id_usuario = param2 ";

                string sqlInsert = @"insert into dbo.T_Profesor_Grupo(id_grupo, id_usuario)
                                    values(param1, param2)";

                Parametros[] paramUpdate = new Parametros[2];   
                paramUpdate[0] = new Parametros(pGrupo.Id, "param1");
                paramUpdate[1] = new Parametros("", "param2");
                
                Parametros[] paramInsert = new Parametros[2];
                paramInsert[0] = new Parametros(pGrupo.Id, "param1");
                paramInsert[1] = new Parametros("", "param2");

                Modulo.comparaListas(pIdsAP, pIdsBD, sqlUpdate, sqlInsert, paramUpdate, paramInsert, bitacora, transaction);
               
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }


        /// <summary>
        /// Método de la clase encargada de conseguir todos los grupos de un profesor.
        /// </summary>
        /// <param name="pIdProfesor">Profesor que va a ser asociado al grupo, tipo int</param>
        /// <remarks></remarks>
        public List<CL_Grupo> buscarGruposProfesor(int pIdProfesor)
        {
            String psp = "dbo.sp_buscar_grupos_de_profesor";
            Parametros []parametros = new Parametros[1];
            parametros[0] = new Parametros(pIdProfesor, "idProfesor");
            List<CL_Grupo> grupos = new List<CL_Grupo>();
            CL_Grupo grupo = null;
            try
            {
                //invocar y ejecutar...  
                SqlDataReader reader = _acceso.execute_SP_Consulta(psp, parametros);

                while (reader.Read())
                {
                    grupo = new CL_Grupo(reader.GetInt32(0), reader.GetInt32(2),
                                        Convert.ToInt32(reader.GetString(1)));
                    grupos.Add(grupo);
                }

                return grupos;
            }
            catch (Exception ex)
            {
                throw new System.Exception(ex.Message);
            }
        }


        /// <summary>
        /// Método de la clase que busca los estudiantes de un grupo.
        /// </summary>
        /// <param name="pIdGrupo">In del grupo, tipo int</param>
        /// <remarks></remarks>
        public List<CL_Grupo> listarGruposDeProfesor(int pidProfesor)
        {
            string psp = @"dbo.sp_buscar_grupos_de_profesor";
            Parametros[] parametros = new Parametros[1];
            parametros[0] = new Parametros(pidProfesor, "idProfesor");
            List<CL_Grupo> grupos = new List<CL_Grupo>();
            try
            {
                SqlDataReader reader = (SqlDataReader)_acceso.execute_SP_Consulta(psp, parametros);
                CL_Grupo grupo = null;
                while (reader.Read())
                {

                    grupo = new CL_Grupo(reader.GetInt32(0), reader.GetInt32(2),
                                        Convert.ToInt32(reader.GetString(1)));
                    grupos.Add(grupo);
                }

                reader.Close();
                return grupos;

            }
            catch (Exception ex)
            {
                throw ex;
            }
        }



        /// <summary>
        /// Método de la clase que busca grupos de un curso
        /// </summary>
        /// <param name="pIdCurso">Id del curso, tipo int</param>
        /// <remarks></remarks>
        public List<CL_Grupo> listarGruposDeCurso(int pidCurso)
        {
            string psp = @"dbo.sp_buscar_grupos_curso";
            Parametros[] parametros = new Parametros[1];
            parametros[0] = new Parametros(pidCurso, "idCurso");
            List<CL_Grupo> grupos = new List<CL_Grupo>();
            try
            {
                SqlDataReader reader = (SqlDataReader)_acceso.execute_SP_Consulta(psp, parametros);
                CL_Grupo grupo = null;
                while (reader.Read())
                {

                    grupo = new CL_Grupo(reader.GetInt32(0), reader.GetInt32(2),
                                        Convert.ToInt32(reader.GetString(1)));
                    grupos.Add(grupo);
                }

                reader.Close();
                return grupos;

            }
            catch (Exception ex)
            {
                throw ex;
            }
        }


        /// <summary>
        /// Método de la clase encargada de insertar una nueva Carrera a la BD
        /// </summary>
        /// <param name="pGrupo">Objeto carrera, tipo Carrera</param>
        /// <param name="pUsuario">Usuario que realiza la accion, tipo int</param>
        /// <remarks></remarks>
        internal void eliminarGrupo(int pidGrupo, int pIdUsuario)//parametros del grupo
        {

            Parametros[] parametros = new Parametros[1];
            String sql = @"Update dbo.T_Grupo SET estado = 0 where dbo.T_Grupo.id_grupo = param1";


            parametros[0] = new Parametros(pidGrupo, "param1");

            try
            {
                int id;

                id = _acceso.executeSQLInsert(sql, parametros);

                if (id != -1)
                {
                    //BITACORA
                    Modulo.insertarBitacora(pIdUsuario, "Eliminacion de un Grupo", id, 5, 2);
                    //---------------
                }
            }
            catch (Exception)
            {
                throw new Exception("Error al eliminar el grupo y devolver la Base de Datos a un estado válido.");
            }

        }



        // <summary>
        /// Método de la clase que busca los ids de los grupos de un estudiante
        /// </summary>
        /// <param name="pIdEstudiante">In del estudiante tipo int</param>
        /// <remarks></remarks>
        public List<int> buscarIdsGrupoEstudiante(int pIdEstudiante)
        {

            string psp = @"sp_obtener_ids_grupos_de_estudiante";
            Parametros[] parametros = new Parametros[1];
            parametros[0] = new Parametros(pIdEstudiante , "idEstudiante");

            try
            {
                SqlDataReader reader = _acceso.execute_SP_Consulta(psp, parametros);
                List<int> ids = new List<int>();
                while (reader.Read())
                {
                    ids.Add((int)reader["id_grupo"]);
                }

                reader.Close();
                return ids;

            }
            catch (Exception ex)
            {
                throw ex;
            }

        }



        /// <summary>
        /// Método de la clase encargada de insertar la asociacion entre estudiante y grupo.
        /// </summary>
        /// <param name="pIdEstudiante">Id del estudiante, tipo int</param>
        /// <param name="pGrupos">Arreglo con los ids de los grupos, tipo ArrayList</param>
        /// <param name="pUsuario">Usuario que realiza la accion, tipo int</param>
        /// <remarks></remarks>
        public void asociarGrupoConEstudiante(int pIdEstudinte, List<int> pGrupos, int pIdUsuario)
        {
            SqlConnection conexion = _acceso.GetConnection();
            conexion.Open();
            SqlTransaction transaction = conexion.BeginTransaction(IsolationLevel.ReadCommitted);

            try
            {
                Parametros[] parametros = new Parametros[2];
                string sql = @"insert into dbo.T_Estudiante_Grupo(id_usuario, id_grupo)
                                values(param1, param2) ";

                int idRelacion = 0;

                for (int i = 0; i < pGrupos.Count; i++)
                {
                    parametros[0] = new Parametros(pIdEstudinte, "param1");
                    parametros[1] = new Parametros(pGrupos[i], "param2");

                    idRelacion = _acceso.executeSQLInsertTransation(transaction, sql, parametros);

                    Modulo.insertarBitacoraParaTransaccion(transaction, pIdUsuario,
                   "Matricular un estudiante a un grupo.", idRelacion, 15, 1);

                }

                new BlogPersistente().activarBlog(pIdEstudinte, pIdUsuario, transaction);

                transaction.Commit();
                conexion.Close();
            }
            catch (Exception ex )
            {
                try
                {
                    transaction.Rollback();
                  //  throw new Exception("Hubo un error al intentar matricular el estudiante.");
                    throw ex;
                }
                catch (Exception e )
                {
                    throw e;
                    //throw new Exception("Error al matricular el estudiante y devolver la Base de Datos a un estado válido.");
                }
            }
            finally
            {
                conexion.Close();
            }
        }

        
        public void modificarAsociacionGruposEstudiante(int pIdEstudiante, List<int> pIdsAp, List<int> pIdBd, int pIdUsuario)
        {

            SqlConnection conexion = _acceso.GetConnection();
            conexion.Open();
            SqlTransaction transaction = conexion.BeginTransaction(IsolationLevel.ReadCommitted);

            try
            {

                 if (pIdsAp.Count == 0)//Si el estudiante ya no esta asociado a algun grupo, se le desactiva el blog.
                {
                    new BlogPersistente().desactivarBlog(pIdEstudiante, pIdUsuario, transaction);
                }


                EsBitacora bitacora = new EsBitacora();
                bitacora.Descripcion = "Cambio de los grupos de un estudiante";
                bitacora.IdUsuario = pIdUsuario;
                bitacora.Tipo= "15";
                string sqlDelete = @"delete dbo.T_Estudiante_Grupo 
                                    where id_usuario = param1 and
                                    id_grupo = param2";

                Parametros[] paramDelete = new Parametros[2];
                paramDelete[0] = new Parametros(pIdEstudiante, "param1");
                paramDelete[1] = new Parametros("" , "param2");

                string sqlInsert = @"insert into dbo.T_Estudiante_Grupo(id_usuario, id_grupo)
                                    values(param1, param2)";

                Parametros[] paramInsert = new Parametros[2];
                 paramInsert[0] = new Parametros(pIdEstudiante, "param1");
                paramInsert[1] = new Parametros("" , "param2");

                Modulo.comparaListas(pIdsAp, pIdBd, sqlDelete, sqlInsert, paramDelete, paramInsert, bitacora, transaction);

     
            }
            catch (Exception ex)
            {
                transaction.Rollback();
                throw ex;
            }
        }



        /// <summary>
        /// Método de la clase encargada de conseguir todos los grupos de un profesor.
        /// </summary>
        /// <param name="pIdProfesor">Profesor que va a ser asociado al grupo, tipo int</param>
        /// <remarks></remarks>
        public List<CL_Grupo> buscarGruposEstudiante(int pIdEstudiante)
        {
            String psp = "sp_buscar_grupos_de_estudiante";
            Parametros[] parametros = new Parametros[1];
            parametros[0] = new Parametros(pIdEstudiante, "idEstudiante");
            List<CL_Grupo> grupos = new List<CL_Grupo>();
            CL_Grupo grupo = null;
            try
            {
                //invocar y ejecutar...  
                SqlDataReader reader = _acceso.execute_SP_Consulta(psp, parametros);

                while (reader.Read())
                {
                    grupo = new CL_Grupo(reader.GetInt32(0), reader.GetInt32(2),
                                        Convert.ToInt32(reader.GetString(1)));
                    grupos.Add(grupo);
                }

                return grupos;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
              
               
    }
}
